package org.thanos.demo.config;

import com.baomidou.dynamic.datasource.processor.DsProcessor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ObjectUtils;
import org.thanos.demo.service.TenantService;
import org.thanos.demo.service.TenantVO;

import javax.sql.DataSource;
import java.lang.reflect.Parameter;
import java.util.Objects;

@Configuration
public class DynamicDsProcessor extends DsProcessor {

    private static final String PREFIX = "#";
    private static final String DEFAULT_PARAMETER = "siteId";

    @Autowired
    private DataSourceManager dataSourceManager;

    @Autowired
    private TenantService tenantService;

    public DynamicDsProcessor() {
    }

    public boolean matches(String key) {
        return key.startsWith(PREFIX);
    }

    public String doDetermineDatasource(MethodInvocation invocation, String key) {
        Integer siteId = Integer.valueOf(this.getParameterValue(invocation, key.replace(PREFIX, "")));
        TenantVO siteDb = tenantService.queryTenantById(siteId);
        if (Objects.isNull(siteDb)) {
            throw new RuntimeException("DataSource:" + siteId + " unavailable.");
        }
        DataSource dbSource = this.dataSourceManager.getDbSource(siteId, siteDb);
        if (dbSource != null) {
            return siteDb.getDbName();
        } else {
            throw new RuntimeException("DataSource:" + siteId + " unavailable.");
        }
    }

    private String getParameterValue(MethodInvocation invocation, String keyParameter) {
        if (ObjectUtils.isEmpty(keyParameter)) {
            keyParameter = DEFAULT_PARAMETER;
        }
        Parameter[] parameters = invocation.getMethod().getParameters();
        for (int index = 0; index < parameters.length; ++index) {
            if (parameters[index].getName().equalsIgnoreCase(keyParameter)) {
                Object argument = invocation.getArguments()[index];
                return String.valueOf(argument);
            }
        }
        throw new RuntimeException("parameter not found.");
    }
}
